package com.nanjia.boot.product.sku.spec.value.service.impl;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nanjia.boot.common.enums.StatusEnum;
import com.nanjia.boot.core.security.util.SecurityUtils;
import com.nanjia.boot.product.sku.converter.ProductSkuConverter;
import com.nanjia.boot.product.sku.mapper.ProductSkuMapper;
import com.nanjia.boot.product.sku.model.entity.ProductSku;
import com.nanjia.boot.product.sku.model.form.ProductSkuConnectSpecValueForm;
import com.nanjia.boot.product.sku.model.form.ProductSkuForm;
import com.nanjia.boot.product.sku.spec.value.converter.SkuSpecValueConverter;
import com.nanjia.boot.product.sku.spec.value.mapper.SkuSpecValueMapper;
import com.nanjia.boot.product.sku.spec.value.model.entity.SkuSpecValue;
import com.nanjia.boot.product.sku.spec.value.model.form.SkuSpecValueForm;
import com.nanjia.boot.product.sku.spec.value.model.query.SkuSpecValueQuery;
import com.nanjia.boot.product.sku.spec.value.model.vo.SkuSpecValueVO;
import com.nanjia.boot.product.sku.spec.value.model.vo.SpecGroupValueVo;
import com.nanjia.boot.product.sku.spec.value.model.vo.SpuSkuSpecGroupSpecValueVo;
import com.nanjia.boot.product.sku.spec.value.service.SkuSpecValueService;
import com.nanjia.boot.product.spec.group.converter.SpecGroupConverter;
import com.nanjia.boot.product.spec.group.mapper.SpecGroupMapper;
import com.nanjia.boot.product.spec.group.model.entity.SpecGroup;
import com.nanjia.boot.product.spec.value.converter.SpecValueConverter;
import com.nanjia.boot.product.spec.value.mapper.SpecValueMapper;
import com.nanjia.boot.product.spec.value.model.entity.SpecValue;
import com.nanjia.boot.product.spec.value.model.form.SpecValueForm;
import com.nanjia.boot.product.spu.converter.ProductSpuConverter;
import com.nanjia.boot.product.spu.mapper.ProductSpuMapper;
import com.nanjia.boot.product.spu.model.entity.ProductSpu;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * SKU与规格值关联服务实现类
 *
 * @author 周洋
 * @since 2025-07-10 16:36
 */
@Service
@RequiredArgsConstructor
public class SkuSpecValueServiceImpl extends ServiceImpl<SkuSpecValueMapper, SkuSpecValue> implements SkuSpecValueService {

    private final SkuSpecValueConverter skuSpecValueConverter;

    private final SpecValueConverter specValueConverter;

    private final ProductSpuConverter productSpuConverter;

    private final ProductSkuConverter productSkuConverter;

    private final SpecGroupConverter specGroupConverter;

    private final SkuSpecValueMapper skuSpecValueMapper;

    private final SpecValueMapper specValueMapper;

    private final ProductSpuMapper productSpuMapper;

    private final ProductSkuMapper productSkuMapper;

    private final SpecGroupMapper specGroupMapper;


    /**
     * 获取SKU与规格值关联分页列表
     *
     * @param queryParams 查询参数
     * @return {@link IPage<SkuSpecValueVO>} SKU与规格值关联分页列表
     */
    @Override
    public IPage<SkuSpecValueVO> getSkuSpecValuePage(SkuSpecValueQuery queryParams) {
        Page<SkuSpecValueVO> pageVO = this.baseMapper.getSkuSpecValuePage(
                new Page<>(queryParams.getPageNum(), queryParams.getPageSize()),
                queryParams
        );
        return pageVO;
    }

    /**
     * 获取SKU与规格值关联表单数据
     *
     * @param id SKU与规格值关联ID
     * @return SKU与规格值关联表单数据
     */
    @Override
    public SkuSpecValueForm getSkuSpecValueFormData(Long id) {
        SkuSpecValue entity = this.getById(id);
        return skuSpecValueConverter.toForm(entity);
    }

    /**
     * 新增SKU与规格值关联
     *
     * @param formData SKU与规格值关联表单对象
     * @return 是否新增成功
     */
    @Override
    public boolean saveSkuSpecValue(SkuSpecValueForm formData) {
        SkuSpecValue entity = skuSpecValueConverter.toEntity(formData);
        return this.save(entity);
    }

    /**
     * 更新SKU与规格值关联
     *
     * @param id       SKU与规格值关联ID
     * @param formData SKU与规格值关联表单对象
     * @return 是否修改成功
     */
    @Override
    public boolean updateSkuSpecValue(Long id, SkuSpecValueForm formData) {
        SkuSpecValue entity = skuSpecValueConverter.toEntity(formData);
        return this.updateById(entity);
    }

    /**
     * 删除SKU与规格值关联
     *
     * @param ids SKU与规格值关联ID，多个以英文逗号(,)分割
     * @return 是否删除成功
     */
    @Override
    public boolean deleteSkuSpecValues(String ids) {
        Assert.isTrue(StrUtil.isNotBlank(ids), "删除的SKU与规格值关联数据为空");
        // 逻辑删除
        List<Long> idList = Arrays.stream(ids.split(","))
                .map(Long::parseLong)
                .toList();
        return this.removeByIds(idList);
    }

    /**
     * 通过skuId获取待选specValue
     *
     * @param id skuId
     * @return vo
     */
    @Override
    public SpuSkuSpecGroupSpecValueVo getSpuSkuSpecGroupSpecValueVo(Long id) {
        SpuSkuSpecGroupSpecValueVo vo = new SpuSkuSpecGroupSpecValueVo();

        ProductSku productSku = productSkuMapper.selectById(id);
        if (productSku != null) {
            vo.setSkuForm(productSkuConverter.toForm(productSku));

            ProductSpu productSpu = productSpuMapper.selectById(productSku.getSpuId());
            vo.setSpuForm(productSpuConverter.toForm(productSpu));

            LambdaQueryWrapper<SpecGroup> specGroupQueryWrapper = new LambdaQueryWrapper<>();
            specGroupQueryWrapper.eq(SpecGroup::getSpuId, productSku.getSpuId()).eq(SpecGroup::getStatus, StatusEnum.ENABLE.getValue());

            List<SpecGroup> list = specGroupMapper.selectList(specGroupQueryWrapper);
            List<SpecGroupValueVo> specGroupValueVoList = new ArrayList<>();
            for (SpecGroup specGroup : list) {
                SpecGroupValueVo specGroupValueVo = new SpecGroupValueVo();
                specGroupValueVo.setSpecGroupForm(specGroupConverter.toForm(specGroup));

                ArrayList<SpecValueForm> specValueForms = new ArrayList<>();
                LambdaQueryWrapper<SpecValue> specValueLambdaQueryWrapper = new LambdaQueryWrapper<>();
                specValueLambdaQueryWrapper.eq(SpecValue::getSpecGroupId, specGroup.getId()).orderByDesc(SpecValue::getId);
                List<SpecValue> specValueList = specValueMapper.selectList(specValueLambdaQueryWrapper);
                for (SpecValue specValue : specValueList) {
                    specValueForms.add(specValueConverter.toForm(specValue));
                }

                specGroupValueVo.setSpecValueForms(specValueForms);
                specGroupValueVoList.add(specGroupValueVo);

            }
            vo.setSpecGroupValueVoList(specGroupValueVoList);


        }
        return vo;
    }

    @Override
    public boolean connectSpecValue(Long id, ProductSkuConnectSpecValueForm form, String ipAddr) {
        // 1. 删除现有关联
        LambdaQueryWrapper<SkuSpecValue> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SkuSpecValue::getSkuId, id);
        this.remove(wrapper);
        List<SpecValue> specValueList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(form.getSpecValueIds())) {
            LambdaQueryWrapper<SpecValue> specValueLambdaQueryWrapper = new LambdaQueryWrapper<>();
            specValueLambdaQueryWrapper.in(SpecValue::getId, form.getSpecValueIds());
            specValueList = specValueMapper.selectList(specValueLambdaQueryWrapper);
        }
        // 2. 创建新关联
        List<SkuSpecValue> entities = new ArrayList<>();
        for (Long specValueId : form.getSpecValueIds()) {
            SpecValue specValue = specValueList.stream().filter(sv -> sv.getId().equals(specValueId)).findFirst().orElse(new SpecValue());
            SkuSpecValue entity = new SkuSpecValue();
            entity.setSkuId(id);
            entity.setSpecGroupId(specValue.getSpecGroupId());
            entity.setSpecValueId(specValueId);
            entity.setCreateBy(SecurityUtils.getUserStrId());
            entity.setUpdateBy(JSONUtil.toJsonStr(SecurityUtils.getUserId()));
            entity.setCreateTime(LocalDateTime.now());
            entity.setUpdateTime(LocalDateTime.now());
            entity.setCreateIp(ipAddr);
            entity.setUpdateIp(ipAddr);
            entities.add(entity);

        }

        // 3. 批量保存
        return this.saveBatch(entities);
    }

    @Override
    public Map<String,Object> getListSpuSkuSpecGroupSpecValueVoBySpuId(Long id) {

        Map<String,Object> map = new HashMap<>();
        ProductSpu productSpu = productSpuMapper.selectById(id);

        // 查询所有的 ProductSku
        List<ProductSku> productSkuList = productSkuMapper.selectList(new LambdaQueryWrapper<ProductSku>().eq(ProductSku::getSpuId, id).eq(ProductSku::getStatus, StatusEnum.ENABLE.getValue()));

        // 查询所有的 SpuSpecGroup 和 SpecValue，并缓存
        List<SpecGroup> specGroupList = specGroupMapper.selectList(new LambdaQueryWrapper<SpecGroup>()
                .eq(SpecGroup::getSpuId, id)
                .eq(SpecGroup::getStatus, StatusEnum.ENABLE.getValue()));
        if (CollectionUtils.isNotEmpty(specGroupList)) {
            Map<Long, List<SpecValue>> specValuesMap = getSpecValuesMap(specGroupList);

            List<SpuSkuSpecGroupSpecValueVo> voList = productSkuList.stream()
                    .filter(Objects::nonNull) // 保证 productSku 不为 null
                    .map(productSku -> createSpuSkuSpecGroupSpecValueVo(productSku, productSpu, specGroupList, specValuesMap))
                    .collect(Collectors.toList());

            map.put("all", voList);
            List<Map<String,Object>> list = new ArrayList<>();
            for (ProductSku productSku : productSkuList) {
                Map<String,Object> map1 = new HashMap<>();
                map1.put("skuId", productSku.getId());
                LambdaQueryWrapper<SkuSpecValue> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(SkuSpecValue::getSkuId, productSku.getId());
                List<SkuSpecValue> result = skuSpecValueMapper.selectList(queryWrapper);
                map1.put("specValues", result);
                list.add(map1);
            }
            map.put("sv", list);

        }
        return map;
    }

    // 提取一个方法来创建 SpuSkuSpecGroupSpecValueVo
    private SpuSkuSpecGroupSpecValueVo createSpuSkuSpecGroupSpecValueVo(ProductSku productSku, ProductSpu productSpu,
                                                                        List<SpecGroup> specGroupList,
                                                                        Map<Long, List<SpecValue>> specValuesMap) {
        SpuSkuSpecGroupSpecValueVo vo = new SpuSkuSpecGroupSpecValueVo();
        ProductSkuForm form = productSkuConverter.toForm(productSku);

        vo.setSkuForm(form);
        vo.setSpuForm(productSpuConverter.toForm(productSpu));

        // 为该产品的 SpuSpecGroup 生成 SpecGroupValueVo 列表
        List<SpecGroupValueVo> specGroupValueVoList = specGroupList.stream()
                .filter(spuSpecGroup -> spuSpecGroup.getSpuId().equals(productSku.getSpuId()))
                .map(spuSpecGroup -> createSpecGroupValueVo(spuSpecGroup, specValuesMap))
                .collect(Collectors.toList());

        vo.setSpecGroupValueVoList(specGroupValueVoList);
        return vo;
    }

    // 提取一个方法来生成 SpecGroupValueVo
    private SpecGroupValueVo createSpecGroupValueVo(SpecGroup specGroup, Map<Long, List<SpecValue>> specValuesMap) {
        SpecGroupValueVo specGroupValueVo = new SpecGroupValueVo();

        specGroupValueVo.setSpecGroupForm(specGroupConverter.toForm(specGroup));

        // 使用缓存的 specValuesMap 来快速获取 SpecValue 列表
        List<SpecValue> specValueList = specValuesMap.get(specGroup.getId());
        if (CollectionUtils.isNotEmpty(specValueList)) {
            List<SpecValueForm> specValueForms = specValueList.stream()
                    .map(specValue -> specValueConverter.toForm(specValue))
                    .collect(Collectors.toList());

            specGroupValueVo.setSpecValueForms(specValueForms);
        }
        return specGroupValueVo;
    }

    // 提取方法来缓存 SpecValue
    private Map<Long, List<SpecValue>> getSpecValuesMap(List<SpecGroup> spuSpecGroupList) {
        // 获取所有 SpecValue
        List<SpecValue> allSpecValues = specValueMapper.selectList(new LambdaQueryWrapper<SpecValue>()
                .in(SpecValue::getSpecGroupId, spuSpecGroupList.stream().map(SpecGroup::getId).collect(Collectors.toList()))
                .eq(SpecValue::getStatus, StatusEnum.ENABLE.getValue()));

        // 使用 Map 按 SpecGroupId 分组
        return allSpecValues.stream()
                .collect(Collectors.groupingBy(SpecValue::getSpecGroupId));
    }

}
